Amazon Time Sync Serviceがマイクロ秒単位で時刻同期できるPTPをサポートしたのでEC2で試してみた
こんにちは。CX事業本部のakkyです。
2週間ほど前となりますが、Amazon Time Sync ServiceがPTPをサポートしました。
この時には見落としてしまったのですが、今回のre:Inventで発表されたAurora Limitless Databaseでは、分散データベースを実現するために精密な時刻同期を必要としており、このために新しいAmazon Time Sync Serviceが使われているという発表がありました。
今回は、このPTP時刻同期をEC2インスタンスで試してみましたのでご紹介します。
Amazon Time Sync Serviceとは?
無料で使えるフルマネージドな時刻同期サービスで、いままではNTPのみがサポートされていました。EC2を使っている方はほぼ間違いなく利用しているはずです。
そんなの設定してないよ?という疑問がわくかもしれませんが、推奨AMIを使い、なおかつ設定を変更していない場合、ntpクライアントで169.254.169.123というサーバにアクセスしていることが分かります。
また、time.aws.comというパブリックNTPサーバも公開されているので、通常のPCからインターネット経由でも使うことができます。
PTPとは?
Precision Time Protocol(PTP)はマイクロ秒精度の時刻同期が可能になるプロトコルです。NTPではミリ秒精度です。
NTPは、やりとりされるパケットでは233ピコ秒の解像度で時刻を表現できるのですが、ネットワークの遅延に対応する仕組みがサーバとクライアントのラウンドトリップタイムの考慮しかないため、ランダムなネットワーク遅延の影響で同期精度はそれほど高くなりません。
一方PTPは専用のスイッチングハブやネットワークカードを使うことで、ネットワークパケットのバッファリング遅延の時間の考慮などが可能になり、より高い同期精度を実現できるようになりました。
PTPの導入にはハードウェアの対応が必要となるため、AWSはNitroのアップグレードによって対応したと考えられます。
参考ページ
EC2でPTPを使ってみた
ここからが本題です。EC2のインスタンスで実際にPTPを時刻ソースとして使ってみました。
ひょっとすると将来的には何も意識せずとも使えるようになるかもしれませんが、現時点では自分で行うべき作業がいくつかあります。
必要な環境
- R7gインスタンスのみの対応となります
- ap-northeast-1(東京)リージョンのみの対応となります
検証環境
- R7g.medium (1vCPU/8GB RAM)
- Amazon Linux 2023(カーネル6.1.61-85.141.amzn2023.aarch64)
- ENAドライバ 2.11.0
- ap-northeast-1リージョン
- インターネットからデータをダウンロードできるVPCサブネットに配置
注意点
カーネルモジュールを新たなものに差し替えますので、作業を誤ると起動しなくなる可能性があります。十分検証してから導入してください。
準備
PTPはENAドライバの対応が必要です。 公式ドキュメントの手順では、ENAドライバがすでにPTPに対応していることを前提に書かれていますが、現時点では対応していないので自分でビルドして入れ替える必要があります。
公式サイトからリンクされているENAドライバのドキュメントと公式ブログを読みつつ作業しました。
まず、デフォルトでPTPが使えないことを確認します。
$ ls /sys/class/ptp ls: cannot access '/sys/class/ptp': No such file or directory
ENAも非対応です。
$ ethtool -T ens5 Time stamping parameters for ens5: Capabilities: software-transmit software-receive software-system-clock PTP Hardware Clock: none Hardware Transmit Timestamp Modes: none Hardware Receive Filter Modes: none
PTPモジュールの設定を確認すると、組み込まれていないということがわかります。
$ grep -w '^CONFIG_PTP_1588_CLOCK=[ym]' /boot/config-`uname -r` CONFIG_PTP_1588_CLOCK=m
では、単にPTPモジュールを読み込めば使えるようになるかというとそうではなく、ENAドライバの対応も必要となります。 そこで、ENAモジュールの設定を見てみると、PTPには対応していないことがわかりました。
対応している場合はparmにphc_enableという項目が出るはずです。ENAドライバのPTP対応には、ビルドの際にENA_PHC_INCLUDE=1という環境変数を設定しておく必要がありますが、この環境変数を設定せずにビルドしているのだと思われます。
$ modinfo ena filename: /lib/modules/6.1.61-85.141.amzn2023.aarch64/kernel/drivers/amazon/net/ena/ena.ko version: 2.10.0g license: GPL description: Elastic Network Adapter (ENA) author: Amazon.com, Inc. or its affiliates (略) parm: debug:Debug level (-1=default,0=none,...,16=all) (int) parm: rx_queue_size:Rx queue size. The size should be a power of 2. Depending on instance type, max value can be up to 16K (int) parm: force_large_llq_header:Increases maximum supported header size in LLQ mode to 224 bytes, while reducing the maximum TX queue size by half. (int) parm: num_io_queues:Sets number of RX/TX queues to allocate to device. The maximum value depends on the device and number of online CPUs. (int) parm: enable_bql:Enable BQL. (int) parm: lpc_size:Each local page cache (lpc) holds N * 1024 pages. This parameter sets N which is rounded up to a multiplier of 2. If zero, the page cache is disabled. Max: 32 (uint)
なお、Amazon Linux 2023ではPTPモジュール自体は既にインストールされていました。
ENAドライバのビルドとインストール
まずはENAドライバをビルドします。modprobeで読み込む方法も紹介されていますが、今回はDKMSで全部管理することにします。
ビルドに必要なパッケージをインストールしましょう。
sudo dnf update sudo dnf install kernel-devel-$(uname -r) git dkms
ドキュメントの「Installing Driver with dkms」の部分をほとんどそのまま使います。一点変えるのは、makeするときに環境変数を渡すところです。
git clone https://github.com/amzn/amzn-drivers.git sudo mv amzn-drivers /usr/src/amzn-drivers-2.11.0
/usr/src/amzn-drivers-2.11.0/dkms.confに以下の内容のファイルを作ります(sudo nanoなどで編集してください)。makeコマンドに環境変数を付けて実行するように変更します。
PACKAGE_NAME="ena" PACKAGE_VERSION="2.11.0" CLEAN="make -C kernel/linux/ena clean" MAKE="ENA_PHC_INCLUDE=1 make -C kernel/linux/ena/ BUILD_KERNEL=${kernelver}" BUILT_MODULE_NAME[0]="ena" BUILT_MODULE_LOCATION="kernel/linux/ena" DEST_MODULE_LOCATION[0]="/updates" DEST_MODULE_NAME[0]="ena" REMAKE_INITRD="yes" AUTOINSTALL="yes"
ビルドしてインストールします。
sudo dkms add -m amzn-drivers -v 2.11.0 sudo dkms build -m amzn-drivers -v 2.11.0 sudo dkms install -m amzn-drivers -v 2.11.0
モジュールの設定
PTPモジュールをシステム起動時に読み込ませるには、/etc/modules-load.d/ptp.confというファイルを作成し、モジュール名のptpを書き込みます。(sudo nano)
ptp
次にenaモジュールの設定を行います。PTPを有効にするにはphc_enable=1というオプションを付ける必要があります。そのため、/etc/modprobe.d/ena.confというファイルを作成し、以下のような内容にします。(sudo nano)
options ena phc_enable=1
ここまで出来たらインスタンスを再起動してください。
動作確認
再びログインするとPTPが使えるようになっているはずです。
まずenaモジュールが切り替わっていることを確認します。phc_enableが増えていますね。
$ modinfo ena filename: /lib/modules/6.1.61-85.141.amzn2023.aarch64/extra/ena.ko version: 2.11.0g license: GPL description: Elastic Network Adapter (ENA) author: Amazon.com, Inc. or its affiliates srcversion: 4A65CC132E6C115C57322E9 alias: pci:v00001D0Fd0000EC21sv*sd*bc*sc*i* alias: pci:v00001D0Fd0000EC20sv*sd*bc*sc*i* alias: pci:v00001D0Fd00001EC2sv*sd*bc*sc*i* alias: pci:v00001D0Fd00000EC2sv*sd*bc*sc*i* alias: pci:v00001D0Fd00000051sv*sd*bc*sc*i* depends: ptp name: ena vermagic: 6.1.61-85.141.amzn2023.aarch64 SMP mod_unload modversions aarch64 parm: debug:Debug level (-1=default,0=none,...,16=all) (int) parm: rx_queue_size:Rx queue size. The size should be a power of 2. Depending on instance type, max value can be up to 16K (int) parm: force_large_llq_header:Increases maximum supported header size in LLQ mode to 224 bytes, while reducing the maximum TX queue size by half. (int) parm: num_io_queues:Sets number of RX/TX queues to allocate to device. The maximum value depends on the device and number of online CPUs. (int) parm: enable_bql:Enable BQL. (int) parm: lpc_size:Each local page cache (lpc) holds N * 1024 pages. This parameter sets N which is rounded up to a multiplier of 2. If zero, the page cache is disabled. Max: 32 (uint) parm: phc_enable:Enable PHC. (uint)
デバイスファイルを確認してみます。
$ ls /sys/class/ptp ptp0
ありました!ethtoolでも見てみると、デバイス番号0が出ています。
$ ethtool -T ens5 Time stamping parameters for ens5: Capabilities: software-transmit software-receive software-system-clock PTP Hardware Clock: 0 Hardware Transmit Timestamp Modes: none Hardware Receive Filter Modes: none
chronyの設定
chronyはNTPクライアントですが、PTPにも対応しています(私も今回初めて知りました)
/etc/chrony.confに以下の内容を追加して、再起動します。
refclock PHC /dev/ptp0 poll 0 delay 0.000010 prefer
sudo systemctl restart chronyd chronyc sources
すると、PHC0(PTP Hardware Clock)に*が付き、優先使用されるようになりました。
$ chronyc sources MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== #* PHC0 0 0 377 0 +137ns[ +202ns] +/- 5030ns ^- 169.254.169.123 1 4 17 2 -1420ns[-1373ns] +/- 47us (略)
トラッキング情報を見てみました。
$ chronyc tracking Reference ID : 50484330 (PHC0) Stratum : 1 Ref time (UTC) : Thu Nov 30 08:34:18 2023 System time : 0.000000003 seconds fast of NTP time Last offset : -0.000000013 seconds RMS offset : 0.000000019 seconds Frequency : 4.736 ppm fast Residual freq : -0.000 ppm Skew : 0.006 ppm Root delay : 0.000010000 seconds Root dispersion : 0.000000887 seconds Update interval : 1.0 seconds Leap status : Normal
以下の出力がNTPの場合です。
$ chronyc tracking Reference ID : A9FEA97B (169.254.169.123) Stratum : 2 Ref time (UTC) : Thu Nov 30 08:42:32 2023 System time : 0.000000277 seconds slow of NTP time Last offset : +0.000000094 seconds RMS offset : 0.000001779 seconds Frequency : 4.749 ppm fast Residual freq : +0.000 ppm Skew : 0.028 ppm Root delay : 0.000076807 seconds Root dispersion : 0.000033963 seconds Update interval : 16.2 seconds Leap status : Normal
比較すると、わずかながら全体的にPTPのほうが特性が良くなっていることがわかりますね。 Root delayがサーバとの遅延なので重要な点かと思うのですが、PTPは10us決め打ちのようにも見えます。 また、NTPはUpdate intervalが変化するものの、PTPはしばらく置いても1秒のままでした。
testptpコマンド(おまけ)
ソースコードのドキュメントにPHC timestampとして直接タイムスタンプを取るtestptpというコマンドが紹介されています。 これはLinuxカーネルのソースコードに付属されているテスト用コマンドです。
ソースコードを取ってきてビルドすると使えます。
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.64.tar.xz tar xvf linux-6.1.64.tar.xz linux-6.1.64/tools/testing/selftests cd linux-6.1.64/tools/testing/selftests/ptp make
sudoを付けて実行します。
$ sudo ./testptp -d /dev/ptp0 -k 1 system and phc clock time offset request okay system time: 1701334331.629123687 phc time: 1701334331.629126222 system time: 1701334331.629127239 system/phc clock time offset is -759 ns system clock time delay is 3552 ns
まとめ
EC2でPTPを使う方法をご紹介しました。カーネルモジュールをビルドし、実際に時刻同期ができることを確認できました。
PTP(IEEE1588)については以前から知っていたのですが、実際に使うとなると専用の機材が必要で個人にはとても無理でした。これがクラウドで使えるとはいい時代です。
ふつうの使い方でここまでの時刻同期精度が必要とされることは少ないと思いますが、これが分散データベースの基盤となっていると思うと興味深いですね。